package cn.virens.util.page;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.annotation.JSONField;

/**
 * 分页查询
 * 
 * @作者 : loioi
 * @创建时间 :2017年8月3日 下午3:13:39
 */
public class Page implements Serializable {

	private static final long serialVersionUID = -3486086036835371165L;
	private int offset = 0;
	private int limit = 10;
	private boolean count = true;

	private List<SortField> sorts;
	private Map<String, Object> params; // 参数，pojo or map

	public Page() {
	}

	public Page(int offset, int limit) {
		this.offset = offset;
		this.limit = limit;
	}

	/**
	 * 获取起始记录数
	 * 
	 * @return
	 */
	public int getOffset() {
		return offset;
	}

	/**
	 * 设置起始记录数
	 * 
	 * @param pageNo
	 */
	public void setOffset(int offset) {
		this.offset = offset;
	}

	/**
	 * 获取每页条数
	 * 
	 * @return
	 */
	public int getLimit() {
		return limit;
	}

	/**
	 * 设置每页条数
	 * 
	 * @param limit
	 */
	public void setLimit(int limit) {
		this.limit = limit;
	}

	/**
	 * 获取 当前页面数
	 * 
	 * @return
	 */
	@JSONField(serialize = false)
	public int getPageNo() {
		return ((int) Math.ceil((double) offset / limit) + 1);
	}

	/**
	 * 设置页码，从第一页开始
	 * 
	 * @param pageNo
	 */
	public void setPageNo(int pageNo) {
		this.setOffset((pageNo - 1) * limit);
	}

	/**
	 * 获取 每页多少条
	 * 
	 * @return
	 */
	@JSONField(serialize = false)
	public int getPageSize() {
		return limit < 0 ? Integer.MAX_VALUE : limit;
	}

	/**
	 * 设置 每页多少条
	 * 
	 * @param pageSize
	 */
	public void setPageSize(int pageSize) {
		this.setLimit(pageSize);
	}

	public boolean isCount() {
		return count;
	}

	public void setCount(boolean count) {
		this.count = count;
	}

	public List<SortField> getSorts() {
		return sorts;
	}

	/**
	 * 获取排序方式,以字符串形式获取
	 * 
	 * @return
	 * @return
	 */
	public String generateSort() {
		if (CollectionUtils.isEmpty(sorts)) {
			return null;
		} else {
			StringBuilder builder = new StringBuilder();
			for (SortField sort : sorts) {
				builder.append(",");
				builder.append(sort.field);
				builder.append(" ");
				builder.append(sort.direction);
			}
			builder.deleteCharAt(0);

			return builder.toString();
		}
	}

	public void setSorts(List<SortField> sorts) {
		this.sorts = sorts;
	}

	/**
	 * 是否跳过分页
	 * 
	 * @return
	 */
	public boolean skip() {
		return !(limit > 0 || CollectionUtils.isEmpty(sorts));
	}

	/**
	 * 添加排序方式
	 * 
	 * @param field
	 */
	public void addSort(String field) {
		this.addSort(field, null);
	}

	/**
	 * 添加排序方式
	 * 
	 * @param field
	 * @param direction
	 */
	public void addSort(String field, String direction) {
		if (this.sorts == null) {
			this.sorts = new ArrayList<>();
		}

		this.sorts.add(new SortField(field, direction));
	}

	public String getParam(String key) {
		return getParam(key, null);
	}

	public String getParam(String key, String defaultValue) {
		return MapUtils.getString(params, key, defaultValue);
	}

	public Map<String, Object> getParams() {
		return params;
	}

	public void setParams(Map<String, Object> params) {
		this.params = params;
	}

	public void addParam(String key, Object value) {
		if (this.params == null) {
			this.params = new HashMap<>();
		}
		this.params.put(key, value);
	}

	@Override
	public String toString() {
		return "PageInfo [offset=" + offset + ", limit=" + limit + ", count=" + count + "]";
	}

	public static class SortField implements Serializable {
		private static final long serialVersionUID = 6699821430074341390L;
		private String field;
		private Direction direction;

		public String getField() {
			return field;
		}

		public void setField(String field) {
			this.field = field;
		}

		public Direction getDirection() {
			return direction;
		}

		public void setDirection(Direction direction) {
			this.direction = direction;
		}

		public SortField(String field) {
			this(field, Direction.ASC);
		}

		public SortField(String field, String direction) {
			this(field, Direction.pares(direction));
		}

		public SortField(String field, Direction direction) {
			this.field = field;
			this.direction = direction;
		}

		@Override
		public String toString() {
			return field + " " + direction.name();
		}
	}

	public enum Direction {
		ASC, DESC;

		public static Direction pares(String direction) {
			return StringUtils.equalsIgnoreCase(direction, "ASC") ? ASC : DESC;
		}
	}
}
